package com.eascs.admin.o2o.user;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;

import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.dubbo.config.annotation.Reference;
import com.eascs.common.util.StringUtil;
import com.eascs.web.sso.EaSsoService;
import com.eascs.web.sso.MenuItem;
import com.eascs.web.sso.User;
import com.eascs.workflow.common.entity.sys.ActOrgEntity;
import com.eascs.workflow.common.entity.sys.SysResources;
import com.eascs.workflow.common.entity.sys.SysRole;
import com.eascs.workflow.common.entity.sys.SysUser;
import com.eascs.workflow.common.service.sys.SysOrgService;
import com.eascs.workflow.common.vo.ModelResult;

@Service
public class EaSsoServiceImpl implements EaSsoService {
	private final static Integer RESOURCE_TYPE_MENU = 1;
	private final static String PARENT_ID_TOP = "-1";
	/** 总部 */
	private final static String ROOT_ORG_PARENT_ID = "-1";

	@Inject
	private EaSsoDao eaSsoDao;
	@Reference
	private com.eascs.workflow.common.service.sys.SysPermissionService sysPermissionService;
	@Reference
	private SysOrgService sysOrgService;

	@Override
	public User getUserByAccount(String account) {
		User user = eaSsoDao.getUserByAccount(account);
		if (null == user || StringUtil.isNull(user.getNo()))
			return null;
		buildPermissionInfo(user);
		return user;
	}

	private void buildPermissionInfo(User user) {

		// setSuperAdministrator
		ModelResult<Boolean> checkIsAdmin = sysPermissionService.checkIsAdmin(user.getNo());
		user.setSuperAdministrator(checkIsAdmin.getModel());
		// setCloseAuth
		ModelResult<Boolean> checkClose = sysPermissionService.checkAuth(user.getNo(), SysRole.ROLE_DELPROCESS_CODE);
		user.setCloseAuth(checkClose.getModel());

		// get sysResourcess
		SysUser sysUser = new SysUser();
		sysUser.setEmployeeNo(Integer.valueOf(user.getNo()));
		ModelResult<List<SysResources>> modelResult = sysPermissionService.queryResourcesByUser(sysUser);
		List<SysResources> sysResourcess = modelResult.getModel();
		if (null == sysResourcess)
			sysResourcess = new ArrayList<>();

		// build getMenuItemTree
		user.getMenuItemTree().addAll(buildMenuItemTree(sysResourcess));

		// build data permission
		buildDataPermissionStr(user);

		if (user.isSuperAdministrator())
			return;

		// build permissionCodeMap
		for (SysResources sysResources : sysResourcess) {
			if (StringUtil.isNull(sysResources.getResourceCode()))
				continue;
			user.getPermissionCodeMap().put(sysResources.getResourceCode(), true);
		}

		// build PermissionUrlMap
		ModelResult<List<SysResources>> allResourcesResult = sysPermissionService.selectResourcesList();
		for (SysResources sysResources : allResourcesResult.getModel()) {
			String uri = buildUri(sysResources.getResourceUrl());
			if (StringUtil.isNull(uri))
				continue;
			user.getPermissionUrlMap().put(uri, false);
		}
		for (SysResources sysResources : sysResourcess) {
			String uri = buildUri(sysResources.getResourceUrl());
			if (StringUtil.isNull(uri))
				continue;
			user.getPermissionUrlMap().put(uri, true);
		}

	}

	// build data permission str
	private void buildDataPermissionStr(User user) {
		// build data Permission string
		String dataPermissionStr = " 99 != 99 and  "; // 无权限
		if (!StringUtils.isEmpty(user.getNo())) {
			ModelResult<List<ActOrgEntity>> modelResult = sysOrgService.getOrgListByRoleAndUser(user.getNo());
			if (modelResult.isSuccess() && modelResult.getModel() != null) {
				List<ActOrgEntity> orgAll = new ArrayList<>();
				List<ActOrgEntity> actOrgList = modelResult.getModel();
				for (ActOrgEntity actOrg : actOrgList) {
					if (actOrg.getParentId().equals(ROOT_ORG_PARENT_ID)) {// 总部
						dataPermissionStr = " 99 = 99 and ";
						orgAll = null;
						break;
					}
					List<ActOrgEntity> orgList = sysOrgService.getChildOrgByOrgId(actOrg.getOrgId());
					orgAll.addAll(orgList);
				}
				if (orgAll != null && !orgAll.isEmpty()) {
					StringBuffer dataPermissonBuffer = new StringBuffer();
					dataPermissonBuffer.append(" 99 = 99 and /**PERMISSION_COLUM**/ in (");
					for (ActOrgEntity orgEntity : orgAll) {
						dataPermissonBuffer.append(Integer.valueOf(orgEntity.getUnitNo())).append(",");
					}
					dataPermissionStr = dataPermissonBuffer.substring(0, dataPermissonBuffer.length() - 1)
							+ " ) and ";
				}
			}
		}
		user.setDataPermissionStr(dataPermissionStr);
	}

	public static String buildUri(String url) {
		if (StringUtil.isNull(url))
			return null;
		return url.replaceAll("^http[s]?://[^/]+", "");
	}

	public static void main(String[] args) {
		System.out.println(buildUri("http://abc.com"));
		System.out.println(buildUri("https://abc.com/"));
		System.out.println(buildUri("http://abc.com/index.html"));
		System.out.println(buildUri("http://abc.com/user/index.html"));
	}

	public List<MenuItem> buildMenuItemTree(List<SysResources> sysResourcess) {

		Map<String, SysResources> sysResourcesMap = new HashMap<>();

		SysResources rootSysResources = null;
		// get menu
		for (int i = 0; null != sysResourcess && i < sysResourcess.size(); i++) {
			if (EaSsoServiceImpl.RESOURCE_TYPE_MENU.equals(sysResourcess.get(i).getResourceType())) {
				sysResourcesMap.put(sysResourcess.get(i).getId(), sysResourcess.get(i));
				// find root SysResources
				if (PARENT_ID_TOP.equals(sysResourcess.get(i).getParentId())) {
					rootSysResources = sysResourcess.get(i);
				}
			}
		}
		if (null == rootSysResources)
			return new ArrayList<>();

		// build menu tree
		SysResourcesComparator sysResourcesComparator = new SysResourcesComparator();
		for (SysResources item : sysResourcesMap.values()) {
			String parentId = item.getParentId();
			SysResources parent = sysResourcesMap.get(parentId);
			if (null == parent)
				continue;
			if (null == parent.getSubResources()) {
				parent.setSubResources(new ArrayList<>());
			}
			parent.getSubResources().add(item);
			Collections.sort(parent.getSubResources(), sysResourcesComparator);
		}

		MenuItem rootMenuItem = buildMenuItem(rootSysResources);

		return rootMenuItem.getSubMenuItems();
	}

	private MenuItem buildMenuItem(SysResources sysResource) {
		MenuItem menuItem = new MenuItem();
		menuItem.setId(sysResource.getId());
		menuItem.setCode(sysResource.getResourceCode());
		menuItem.setName(sysResource.getResourceName());
		menuItem.setParentId(sysResource.getParentId());
		menuItem.setUrl(sysResource.getResourceUrl());
		menuItem.setOrder(sysResource.getSort());
		if (null != sysResource.getSubResources()) {
			for (SysResources sysResourceItem : sysResource.getSubResources()) {
				menuItem.getSubMenuItems().add(buildMenuItem(sysResourceItem));
			}
		}
		return menuItem;
	}

	static class SysResourcesComparator implements Comparator<SysResources> {

		@Override
		public int compare(SysResources o1, SysResources o2) {
			if (null == o1.getSort() || null == o2.getSort())
				return 0;
			return o1.getSort() - o2.getSort();
		}

	}

}
